package com.zx.onlineeducation.service.ucenter.controller;

import com.zx.onlineeducation.common.servicebase.exception.OnlineEducationException;
import com.zx.onlineeducation.common.util.JwtUtils;
import com.zx.onlineeducation.service.ucenter.config.WxOpenProperties;
import com.zx.onlineeducation.service.ucenter.entity.MemberDO;
import com.zx.onlineeducation.service.ucenter.service.MemberService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.omg.CORBA.Object;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.UUID;

/**
 * 微信API 前端控制器
 *
 * @author 郑雪
 * @since 2022-01-27
 */
@Api(tags = "微信接口")
@Controller
@RequestMapping("/api/ucenter/wx")
@CrossOrigin // 解决跨域
@Slf4j
public class WxApiController {

    /**
     * 微信开放平台服务接口属性
     */
    @Autowired
    private WxOpenProperties wxOpenProperties;

    /**
     * 发送http请求的工具类
     */
    @Autowired
    private RestTemplate restTemplate;

    /**
     * 会员服务接口
     */
    @Autowired
    private MemberService memberService;

    /**
     * 获取微信授权的二维码
     *
     * @author 郑雪
     * @return 重定向到微信登录二维码页面
     * @since 2022-01-27
     */
    @ApiOperation("获取微信授权的二维码")
    @GetMapping("/login")
    public String getWxCode() {

        // 获取微信授权二维码的baseUrl，%s相当于?代表占位符
        String baseQrcodeUrl = "https://open.weixin.qq.com/connect/qrconnect" +
                "?appid=%s" +
                "&redirect_uri=%s" +
                "&response_type=code" +
                "&scope=snsapi_login" +
                "&state=%s" +
                "#wechat_redirect";

        // 重定向地址
        String redirectUrl = wxOpenProperties.getRedirectUrl();
        try {
            // 对重定向地址进行UTF-8编码
            URLEncoder.encode(redirectUrl, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new OnlineEducationException(20001, e.getMessage());
        }

        // 防止csrf攻击（跨站请求伪造攻击）
        // 一般情况下会使用一个随机数
        String state = UUID.randomUUID().toString().replaceAll("-", "");
        // 为了使用尚硅谷外网的微信回调跳转服务器，这里填写自己在ngrok的前置域
        state = state.length()>0 ? "atguigu" : "";

        // 生成qrcodeUrl，设置%s里面值
        String qrcodeUrl = String.format(
                baseQrcodeUrl,
                wxOpenProperties.getAppId(),
                wxOpenProperties.getRedirectUrl(),
                state);

        // 重定向到请求微信授权二维码的地址
        return "redirect:" + qrcodeUrl;
    }

    /**
     * 获取微信授权的用户信息并登录
     *
     * @author 郑雪
     * @return 重定向到首页
     * @since 2022-01-27
     */
    @ApiOperation("微信扫码登录后的回调方法，用来获取微信用户信息")
    @GetMapping("/callback")
    public String callback(
            @ApiParam(value = "微信授权临时票据code")
            @RequestParam("code") String code,
            @ApiParam(value = "微信授权state")
            @RequestParam("state") String state) {
        log.info("-------------微信授权结果----------------");
        log.info("code：{}", code);
        log.info("state：{}", state);
        log.info("---------------------------------------");

        // 通过code获取access_token的baseUrl
        String baseAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token" +
                "?appid=%s" +
                "&secret=%s" +
                "&code=%s" +
                "&grant_type=authorization_code";

        // 生成accessTokenUrl，设置%s里面值
        String accessTokenUrl = String.format(
                baseAccessTokenUrl,
                wxOpenProperties.getAppId(),
                wxOpenProperties.getAppSecret(),
                code);

        // 发送请求获取accessToken
        HashMap<String, Object> accessTokenResponse = restTemplate.getForObject(accessTokenUrl, HashMap.class);
        assert accessTokenResponse != null;
        // 获取access_token（接口调用凭证）
        String accessToken = String.valueOf(accessTokenResponse.get("access_token"));
        // 获取openid（授权用户唯一标识）
        String openid = String.valueOf(accessTokenResponse.get("openid"));

        log.info("-------------微信通过code获取access_token结果----------------");
        log.info("响应对象：{}", accessTokenResponse);
        log.info("access_token：{}", accessToken);
        log.info("openid：{}", openid);
        log.info("---------------------------------------");

        // 根据openid查询会员对象
        MemberDO memberDO = memberService.getMemberByOpenid(openid);

        // 如果会员不存在，则添加会员
        if (memberDO == null) {

            // 通过access_token和openid获取用户基本信息的baseUrl
            String baseUserinfoUrl = "https://api.weixin.qq.com/sns/userinfo" +
                    "?access_token={1}" +
                    "&openid={2}";

            // 发送请求获取userInfo
            HashMap<String, Object> userInfoResponse = restTemplate.getForObject(baseUserinfoUrl, HashMap.class, accessToken, openid);
            assert userInfoResponse != null;
            // 获取用户昵称
            String nickname = String.valueOf(userInfoResponse.get("nickname"));
            // 获取用户性别，1为男性，2为女性
            Integer sex = userInfoResponse.get("sex")!=null ? Integer.parseInt(userInfoResponse.get("sex") + "") : null;
            // 获取用户头像
            String headimgurl = String.valueOf(userInfoResponse.get("headimgurl"));

            // 创建会员对象
            memberDO = new MemberDO();
            memberDO.setOpenid(openid);
            memberDO.setNickname(nickname);
            memberDO.setSex(sex);
            memberDO.setAvatar(headimgurl);

            // 添加会员
            memberService.save(memberDO);
        }

        // 使用jwt生成token字符串
        String jwtToken = JwtUtils.getJwtToken(memberDO.getId(), memberDO.getNickname());

        // 重定向到首页，通过路径传递token字符串
        return "redirect:http://localhost:3000?token=" + jwtToken;
    }
}
